#pragma once
#include "Jquery.h"

Jquery::Jquery(void)
{
	m_pDoc = NULL;
}


Jquery::~Jquery(void)
{

}

Jquery::Jquery(TiXmlElement *pEle)
{
	m_pRoot = pEle;

}


bool Jquery::LoadFile(std::string strFile,bool bIsUtf8XML,std::string strXMLContent)
{
	
	bool bLoadFlag = false;

	if(!LoadDoc(m_doc,strFile,bIsUtf8XML))
	{
		if(strXMLContent != "")
		{
			FileUtil::WriteStr(strFile,strXMLContent);
			bLoadFlag = LoadDoc(m_doc,strFile,bIsUtf8XML);
		}

	}
	else
	{
		bLoadFlag = true;
	}

	bool bIsSucc = false;
	if(bLoadFlag)
	{
		m_pDoc = &m_doc;
		m_pRoot = m_doc.RootElement();
		if(NULL != m_pRoot)
		{
			bIsSucc = true;
		}
	}	

	return bIsSucc;
}


bool Jquery::SetAttr(TiXmlElement* pEle,std::string strAttr,std::string strVale)
{
	if(NULL == pEle)
	{
		return false;
	}

	pEle->SetAttribute(strAttr.c_str(),strVale.c_str());
	return true;
}

bool Jquery::SetAttr(std::string strAttr,std::string strValue)
{
	return SetAttr(m_pRoot,strAttr,strValue);
}


bool Jquery::LoadDoc(TiXmlDocument& doc,std::string strFile,bool bIsUtf8XML)
{
	bool bIsLoadSucc = false;	
	if(bIsUtf8XML)
	{
		bIsLoadSucc = doc.LoadFile(strFile.c_str(),TIXML_ENCODING_UTF8);
	}
	else
	{
		bIsLoadSucc = doc.LoadFile(strFile.c_str(),TIXML_ENCODING_UNKNOWN);
	}

	return bIsLoadSucc;
}


TiXmlElement* Jquery::Find(std::string strSelector)
{
	TiXmlElement* pEle = NULL;
	if(NULL != m_pRoot)
	{
		std::list<TiXmlElement*> listEle;
		std::list<std::string> strSelParts = GetSelectorParts(strSelector);
		Find(m_pRoot,strSelParts,listEle,false);		
		if(listEle.size() != 0)
		{
			pEle = *listEle.begin();
		}
	}

	return pEle;
}

std::list<TiXmlElement*> Jquery::FindAll(std::string strSelector)
{
	std::list<TiXmlElement*> listEle;
	if(NULL != m_pRoot)
	{
		std::list<std::string> strSelParts = GetSelectorParts(strSelector);
		Find(m_pRoot,strSelParts,listEle,true);			
	}

	return listEle;		
}


std::list<std::string> Jquery::GetSelectorParts(std::string strSelector)
{
	while(StringUtil::IndexOf(strSelector," =") != -1)
	{
		strSelector = StringUtil::Replace(strSelector," =","=");
	}

	while(StringUtil::IndexOf(strSelector,"= ") != -1)
	{
		strSelector = StringUtil::Replace(strSelector,"= ","=");
	}

	std::list<std::string> listSelector = StringUtil::Split(strSelector," ");
	return listSelector;
}




bool Jquery::Find(TiXmlElement* pEle,std::list<std::string> listSelector,std::list<TiXmlElement*>& listEle_out,bool bFindAll)
{
	if(listSelector.size() == 0)
	{
		return false;
	}

	std::list<std::string> listSelectorTemp = listSelector;

	std::string strOneSelctor = *(listSelectorTemp.begin());
	listSelectorTemp.erase(listSelectorTemp.begin());


	Find(pEle,strOneSelctor,listSelectorTemp,listEle_out,bFindAll);
	if(listEle_out.size() != 0)
	{
		return true;
	}
	else
	{
		return false;
	}

}


std::string Jquery::GetNodeName(TiXmlElement* pEle)
{
	if(NULL == pEle)
	{
		return "";
	}


	std::string strNodeName = (pEle->Value() == NULL ? "":pEle->Value());
	return strNodeName;
}



bool Jquery::IsAttrExist(TiXmlElement* pEle,std::string strAttr)
{
	if(pEle->Attribute(strAttr.c_str()) == NULL)
	{
		return false;
	}
	else
	{
		return true;
	}

}

std::string Jquery::GetAttr(TiXmlElement* pEle,std::string strAttr,ATTRTYPE attrType)
{
	std::string strVal = "";
	if(IsAttrExist(pEle,strAttr))
	{
		const char* pAttr =  pEle->Attribute(strAttr.c_str());
		strVal = (pAttr== NULL ? "":pAttr) ;
	}


	if(attrType == ACP_2_UTF8)
	{
		strVal = StringUtil::ANSIToUTF8(strVal);

	}
	else if(attrType == UTF8_2_ACP)
	{
		strVal = StringUtil::UTF8T0ANSI(strVal);
	}
	

	return strVal;

}


std::map<std::string,std::string> Jquery::GetAttrMap(std::string strSelector)
{
	std::list<std::string> listAttr = StringUtil::Split(strSelector,"[");
	std::map<std::string,std::string> mapAttr;

	for(std::list<std::string>::iterator it = listAttr.begin(); it != listAttr.end(); it++)
	{
		std::string strAttr = *it;
		int iPosAttrEnd = StringUtil::IndexOf(strAttr,"]");
		if(iPosAttrEnd  >= 0)
		{
			strAttr = StringUtil::Substring(strAttr,0,iPosAttrEnd);
			int iPosValStart = StringUtil::IndexOf(strAttr,"=");

			std::string strAttrName = "";
			std::string strAttrVal = "";
			if(iPosValStart	 >= 0)
			{
				strAttrName = StringUtil::Substring(strAttr,0,iPosValStart);
				strAttrVal =  StringUtil::Substring(strAttr,iPosValStart+1);

				if(strAttrName != "")
				{

					if(StringUtil::StartsWith(strAttrVal,"'")||StringUtil::StartsWith(strAttrVal,"\""))
					{
						strAttrVal = StringUtil::Substring(strAttrVal,1);
					}

					if(StringUtil::EndWith(strAttrVal,"'")||StringUtil::EndWith(strAttrVal,"\""))
					{
						strAttrVal = StringUtil::Substring(strAttrVal,StringUtil::Length(strAttrVal) -1);
						
					}

					mapAttr.insert(std::make_pair(strAttrName,strAttrVal));

				}



			}

		}

	}

	return mapAttr;

}


bool Jquery::IsAttrExist(TiXmlElement* pEle,std::map<std::string,std::string> mapAttr)
{
	bool bIsSucc = true;
	for(std::map<std::string,std::string>::iterator it = mapAttr.begin(); it != mapAttr.end(); it++)
	{
		std::string strAttrName = it->first;
		std::string strAttrVal = it->second;

		if(IsAttrExist(pEle,strAttrName) && GetAttr(pEle,strAttrName,NOCHANGE) == strAttrVal)
		{

		}
		else
		{
			bIsSucc = false; 
			break;
		}

	}

	return bIsSucc;
}


bool Jquery::Parse(std::string strXMLContent,bool bIsUtf8)
{
	bool bFlag = false;
	if(bIsUtf8)
	{
		m_doc.Parse(strXMLContent.c_str(),0,TIXML_ENCODING_UTF8);		
	}
	else
	{
		m_doc.Parse(strXMLContent.c_str(),0,TIXML_ENCODING_UNKNOWN);
	}

	if(m_doc.RootElement() != NULL)
	{
		m_pDoc = &m_doc;
		m_pRoot = m_doc.RootElement();
		return true;
	}
	else
	{
		return false;
	}

}


TiXmlElement* Jquery::GetNode()
{
	return m_pRoot;
}

bool Jquery::Append(TiXmlElement* pEle)
{
	if(pEle == NULL || m_pRoot == NULL)
	{
		return false;
	}

	m_pRoot->InsertEndChild(*pEle);
	return true;
}


bool Jquery::Find(TiXmlElement* pEle, std::string strOneSelctor,const std::list<std::string>& listSubSelector,std::list<TiXmlElement*>& listEle_out,bool bFindAll)
{
	if(NULL == pEle)
	{
		return false;
	}


	int iIdStartPos = StringUtil::IndexOf(strOneSelctor,"#");
	if(iIdStartPos != -1)
	{

		std::string strId = StringUtil::Substring(strOneSelctor,iIdStartPos);
		int iIdEndPos = StringUtil::IndexOf(strId,"[",iIdStartPos);
		if(iIdEndPos != -1)
		{
			strId = StringUtil::Substring(strId,0,iIdEndPos);
		}

		strOneSelctor = StringUtil::Replace(strOneSelctor,strId,"[id='"+StringUtil::Substring(strId,1)+"']");
	}




	std::list<TiXmlElement*> pListEleTemp;
	std::map<std::string,std::string> mapSelector = GetAttrMap(strOneSelctor);
	


	if(listSubSelector.size() == 0)
	{
		int iNodeNameEnd = StringUtil::IndexOf(strOneSelctor,"[");
		std::string strSelectorNodeName = strOneSelctor;

		if(iNodeNameEnd >= 0)
		{
			 strSelectorNodeName = StringUtil::Substring(strOneSelctor,0,iNodeNameEnd);
		}
		
		for (TiXmlElement* pEleChild = pEle->FirstChildElement(); 
			pEleChild != NULL;
			pEleChild = pEleChild->NextSiblingElement())
		{
			if(strSelectorNodeName != "" )
			{
				if((GetNodeName(pEleChild) == strSelectorNodeName) 
					&& (IsAttrExist(pEleChild,mapSelector)))
				{
					listEle_out.push_back(pEleChild);
				}

			}
			else if(IsAttrExist(pEleChild,mapSelector))
			{
				listEle_out.push_back(pEleChild);
			}
	

			if(bFindAll)
			{
				Find(pEleChild,strOneSelctor,listSubSelector,listEle_out,bFindAll);

			}
			else
			{
				if(listEle_out.size() > 0)
				{
					break;
				}
		
			}



		}
	}
	else
	{
		for (TiXmlElement* pEleChild = pEle->FirstChildElement(); 
			pEleChild != NULL;
			pEleChild = pEleChild->NextSiblingElement() ) 
		{
			if((GetNodeName(pEleChild) == strOneSelctor) 
				&& (IsAttrExist(pEleChild,mapSelector)))
			{
				std::list<std::string> listTemp = listSubSelector;
				std::string strSubSelector = *listTemp.begin();
				listTemp.erase(listTemp.begin());

				Find(pEleChild,strSubSelector,listTemp,listEle_out,bFindAll);
			}


			if(bFindAll || listEle_out.size() == 0)
			{

				Find(pEleChild,strOneSelctor,listSubSelector,listEle_out,bFindAll);
			}

		}
	}
	return true;

}


std::string Jquery::ToString(TiXmlElement* pEle)
{
	TiXmlPrinter printer;
	pEle->Accept(&printer);
	return printer.CStr();

}


bool Jquery::SaveFile()
{
	bool bFlag = false;
	if(NULL != m_pDoc)
	{
		bFlag = m_pDoc->SaveFile();
	}

	return bFlag;
}


bool Jquery::SaveFile(std::string strFilePath)
{
	if(strFilePath == "")
	{
		return false;
	}

	bool bFlag = false;
	if(NULL != m_pDoc)
	{
		bFlag = m_pDoc->SaveFile(strFilePath.c_str());
	}

	return bFlag;

}


bool Jquery::Remove(TiXmlElement* pEle)
 {
	 if(NULL == pEle)
	 {
		 return false;
	 }

	 TiXmlElement *pEleParent = (TiXmlElement *)pEle->Parent();
	 if(pEleParent != NULL)
	 {
		 pEleParent->RemoveChild(pEle);
	 }
	 else
	 {
		 delete pEle;	
	 }

	 return true;

 }